package deviceScript

import (
	"fmt"
	"gitee.com/fierce_wolf/go-fox-edge-common/commEntity"
	"gitee.com/fierce_wolf/go-fox-edge-common/commLogger"
	"gitee.com/fierce_wolf/go-fox-edge-common/edgeEntity"
	"github.com/dop251/goja"
	"go-fox-edge-device/deviceLogger"
)

type OperateNotify struct {
	routineKeys map[string]interface{}
}

func (e *OperateNotify) Notify(_ int64, addMap map[string]commEntity.IEntity, _ map[string]commEntity.IEntity, mdyMap map[string]commEntity.IEntity) {
	for _, v := range addMap {
		operateEntity := v.(*edgeEntity.OperateEntity)
		for routineKey, _ := range e.routineKeys {
			e.RebindScriptEngine(routineKey, operateEntity)
		}
	}

	for _, v := range mdyMap {
		operateEntity := v.(*edgeEntity.OperateEntity)
		for routineKey, _ := range e.routineKeys {
			e.RebindScriptEngine(routineKey, operateEntity)
		}
	}
}

func (e *OperateNotify) RebindScriptEngine(routineKey string, operateEntity *edgeEntity.OperateEntity) {
	if operateEntity.EngineType != "JavaScript" {
		return
	}
	if operateEntity.ServiceType != "device" {
		return
	}

	engine := engineService.getScriptEngine(operateEntity.Manufacturer, operateEntity.DeviceType, routineKey)
	if engine == nil {
		return
	}

	if operateEntity.OperateMode == "include" {
		include := operateEntity.EngineParam["include"]
		runScript(include, engine, operateEntity.MakeServiceKey())
	} else {
		decode := operateEntity.EngineParam["decode"]
		runScript(decode, engine, operateEntity.MakeServiceKey())

		encode := operateEntity.EngineParam["encode"]
		runScript(encode, engine, operateEntity.MakeServiceKey())
	}
}

func runScript(encode interface{}, engine *goja.Runtime, key string) {
	// 定义一个最终的异常拦截，用来防止可能的代码BUG
	defer func() {
		if r := recover(); r != nil {
			deviceLogger.PrintLogger(fmt.Sprintf("deviceScript.runScript() 捕获到异常:%v", r))
		}
	}()

	if encode == nil {
		return
	}

	m := encode.(map[string]interface{})
	_, err := engine.RunString(m["code"].(string))
	if err != nil {
		message := "初始化脚本引擎异常：" + key + "; " + err.Error()
		err := commLogger.Console.Error(message)
		if err != nil {
			return
		}
	}
}
